home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / jpsrc2.zip / JCMAIN.C < prev    next >
C/C++ Source or Header  |  1991-12-13  |  11KB  |  383 lines

  1. /*
  2.  * jcmain.c
  3.  *
  4.  * Copyright (C) 1991, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains a trivial test user interface for the JPEG compressor.
  9.  * It should work on any system with Unix- or MS-DOS-style command lines.
  10.  *
  11.  * Two different command line styles are permitted, depending on the
  12.  * compile-time switch TWO_FILE_COMMANDLINE:
  13.  *    cjpeg [options]  inputfile outputfile
  14.  *    cjpeg [options]  [inputfile]
  15.  * In the second style, output is always to standard output, which you'd
  16.  * normally redirect to a file or pipe to some other program.  Input is
  17.  * either from a named file or from standard input (typically redirected).
  18.  * The second style is convenient on Unix but is unhelpful on systems that
  19.  * don't support pipes.  Also, you MUST use the first style if your system
  20.  * doesn't do binary I/O to stdin/stdout.
  21.  */
  22.  
  23. #include "jinclude.h"
  24. #ifdef INCLUDES_ARE_ANSI
  25. #include <stdlib.h>        /* to declare exit() */
  26. #endif
  27.  
  28. #ifdef THINK_C
  29. #include <console.h>        /* command-line reader for Macintosh */
  30. #endif
  31.  
  32. #ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  33. #define READ_BINARY    "r"
  34. #define WRITE_BINARY    "w"
  35. #else
  36. #define READ_BINARY    "rb"
  37. #define WRITE_BINARY    "wb"
  38. #endif
  39.  
  40. #include "jversion.h"        /* for version message */
  41.  
  42.  
  43. /*
  44.  * PD version of getopt(3).
  45.  */
  46.  
  47. #include "egetopt.c"
  48.  
  49.  
  50. /*
  51.  * This routine determines what format the input file is,
  52.  * and selects the appropriate input-reading module.
  53.  *
  54.  * To determine which family of input formats the file belongs to,
  55.  * we may look only at the first byte of the file, since C does not
  56.  * guarantee that more than one character can be pushed back with ungetc.
  57.  * Looking at additional bytes would require one of these approaches:
  58.  *     1) assume we can fseek() the input file (fails for piped input);
  59.  *     2) assume we can push back more than one character (works in
  60.  *        some C implementations, but unportable);
  61.  *     3) provide our own buffering as is done in djpeg (breaks input readers
  62.  *        that want to use stdio directly, such as the RLE library);
  63.  * or  4) don't put back the data, and modify the input_init methods to assume
  64.  *        they start reading after the start of file (also breaks RLE library).
  65.  * #1 is attractive for MS-DOS but is untenable on Unix.
  66.  *
  67.  * The most portable solution for file types that can't be identified by their
  68.  * first byte is to make the user tell us what they are.  This is also the
  69.  * only approach for "raw" file types that contain only arbitrary values.
  70.  * We presently apply this method for Targa files.  Most of the time Targa
  71.  * files start with 0x00, so we recognize that case.  Potentially, however,
  72.  * a Targa file could start with any byte value (byte 0 is the length of the
  73.  * seldom-used ID field), so we accept a -T switch to force Targa input mode.
  74.  */
  75.  
  76. static boolean is_targa;    /* records user -T switch */
  77.  
  78. #ifdef MSDOS
  79. #define JPEG_EXT        "jpg"
  80. static char *input_ext = "tga";
  81. #endif
  82.  
  83.  
  84.  
  85. LOCAL void
  86. select_file_type (compress_info_ptr cinfo)
  87. {
  88.   int c;
  89.  
  90.   if (is_targa) {
  91. #ifdef TARGA_SUPPORTED
  92.     jselrtarga(cinfo);
  93. #else
  94.     ERREXIT(cinfo->emethods, "Targa support was not compiled");
  95. #endif
  96.     return;
  97.   }
  98.  
  99.   if ((c = getc(cinfo->input_file)) == EOF)
  100.     ERREXIT(cinfo->emethods, "Empty input file");
  101.  
  102.   switch (c) {
  103. #ifdef GIF_SUPPORTED
  104.   case 'G':
  105.     jselrgif(cinfo);
  106. #ifdef MSDOS
  107.     input_ext = "gif";
  108. #endif
  109.     break;
  110. #endif
  111. #ifdef PPM_SUPPORTED
  112.   case 'P':
  113.     jselrppm(cinfo);
  114. #ifdef MSDOS
  115.     input_ext = "ppm";
  116. #endif
  117.     break;
  118. #endif
  119. #ifdef RLE_SUPPORTED
  120.   case 'R':
  121.     jselrrle(cinfo);
  122. #ifdef MSDOS
  123.     input_ext = "rle";
  124. #endif
  125.     break;
  126. #endif
  127. #ifdef TARGA_SUPPORTED
  128.   case 0x00:
  129.     jselrtarga(cinfo);
  130.     break;
  131. #endif
  132.   default:
  133. #ifdef TARGA_SUPPORTED
  134.     ERREXIT(cinfo->emethods, "Unrecognized input file format--did you forget -T ?");
  135. #else
  136.     ERREXIT(cinfo->emethods, "Unrecognized input file format");
  137. #endif
  138.     break;
  139.   }
  140.  
  141.   if (ungetc(c, cinfo->input_file) == EOF)
  142.     ERREXIT(cinfo->emethods, "ungetc failed");
  143. }
  144.  
  145.  
  146. /*
  147.  * This routine gets control after the input file header has been read.
  148.  * It must determine what output JPEG file format is to be written,
  149.  * and make any other compression parameter changes that are desirable.
  150.  */
  151.  
  152. METHODDEF void
  153. c_ui_method_selection (compress_info_ptr cinfo)
  154. {
  155.   /* If the input is gray scale, generate a monochrome JPEG file. */
  156.   if (cinfo->in_color_space == CS_GRAYSCALE)
  157.     j_monochrome_default(cinfo);
  158.   /* For now, always select JFIF output format. */
  159. #ifdef JFIF_SUPPORTED
  160.   jselwjfif(cinfo);
  161. #else
  162.   You shoulda defined JFIF_SUPPORTED.   /* deliberate syntax error */
  163. #endif
  164. }
  165.  
  166.  
  167. LOCAL void
  168. usage (char * progname)
  169. /* complain about bad command line */
  170. {
  171.   fprintf(stderr, "usage: %s ", progname);
  172.   fprintf(stderr, "[-Q quality 0..100] [-o] [-T] [-I] [-a] [-d]");
  173. #ifdef TWO_FILE_COMMANDLINE
  174.   fprintf(stderr, " inputfile outputfile\n");
  175. #else
  176.   fprintf(stderr, " [inputfile]\n");
  177. #endif
  178.   exit(2);
  179. }
  180.  
  181. #ifdef MSDOS
  182.  
  183. /*
  184.  * Compose a filename given a base name and extension.  If file had
  185.  * and extension, throw it away.  We must scan the filename from the
  186.  * right looking for a '.', but stopping if we encounter a path
  187.  * separator character (just in case we are handled a long pathname
  188.  * in which one of the directories has a '.', but the file doesn't).
  189.  */
  190.  
  191. LOCAL void
  192. fix_msdos_filename (char *dest, char *src, char *ext)
  193. {
  194.   int i, l;
  195.   char *dotp;
  196.  
  197.   strcpy(dest, src);
  198.   l = strlen(dest);
  199.   dotp = dest + l; /* Assume there is no extension */
  200.  
  201.   for (i = --l; i >= 0; --i) {
  202.     if (dest[i] == '.') {
  203.       dotp = dest + i;
  204.       break;
  205.     } else if ( dest[i] == '/' || dest[i] == '\\' ||
  206.                 dest[i] == ':') {
  207.       break;
  208.     }
  209.   }
  210.   *dotp++ = '.';
  211.   strcpy(dotp, ext);
  212. }
  213.  
  214. #endif /* MSDOS */
  215.  
  216. /*
  217.  * The main program.
  218.  */
  219.  
  220. GLOBAL void
  221. main (int argc, char **argv)
  222. {
  223. #ifdef MSDOS
  224.   char infname[FILENAME_MAX], outfname[FILENAME_MAX];
  225. #endif
  226.   struct compress_info_struct cinfo;
  227.   struct compress_methods_struct c_methods;
  228.   struct external_methods_struct e_methods;
  229.   int c;
  230.  
  231.   /* On Mac, fetch a command line. */
  232. #ifdef THINK_C
  233.   argc = ccommand(&argv);
  234. #endif
  235.  
  236.   /* Initialize the system-dependent method pointers. */
  237.   cinfo.methods = &c_methods;
  238.   cinfo.emethods = &e_methods;
  239.   jselerror(&e_methods);    /* error/trace message routines */
  240.   jselvirtmem(&e_methods);    /* memory allocation routines */
  241.   c_methods.c_ui_method_selection = c_ui_method_selection;
  242.  
  243.   /* Set up default JPEG parameters. */
  244.   j_c_defaults(&cinfo, 75, FALSE); /* default quality level = 75 */
  245.   is_targa = FALSE;
  246.  
  247.   /* Scan command line options, adjust parameters */
  248.   
  249.   while ((c = egetopt(argc, argv, "IQ:Taod")) != EOF)
  250.     switch (c) {
  251.     case 'I':            /* Create noninterleaved file. */
  252. #ifdef MULTISCAN_FILES_SUPPORTED
  253.       cinfo.interleave = FALSE;
  254. #else
  255.       fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n",
  256.           argv[0]);
  257.       exit(2);
  258. #endif
  259.       break;
  260.     case 'Q':            /* Quality factor. */
  261.       { int val;
  262.     if (optarg == NULL)
  263.       usage(argv[0]);
  264.     if (sscanf(optarg, "%d", &val) != 1)
  265.       usage(argv[0]);
  266.     /* Note: for now, we make force_baseline FALSE.
  267.      * This means non-baseline JPEG files can be created with low Q values.
  268.      * To ensure only baseline files are generated, pass TRUE instead.
  269.      */
  270.     j_set_quality(&cinfo, val, FALSE);
  271.       }
  272.       break;
  273.     case 'T':            /* Input file is Targa format. */
  274.       is_targa = TRUE;
  275.       break;
  276.     case 'a':            /* Use arithmetic coding. */
  277. #ifdef ARITH_CODING_SUPPORTED
  278.       cinfo.arith_code = TRUE;
  279. #else
  280.       fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
  281.           argv[0]);
  282.       exit(2);
  283. #endif
  284.       break;
  285.     case 'o':            /* Enable entropy parm optimization. */
  286. #ifdef ENTROPY_OPT_SUPPORTED
  287.       cinfo.optimize_coding = TRUE;
  288. #else
  289.       fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
  290.           argv[0]);
  291.       exit(2);
  292. #endif
  293.       break;
  294.     case 'd':            /* Debugging. */
  295.       e_methods.trace_level++;
  296.       break;
  297.     case '?':
  298.     default:
  299.       usage(argv[0]);
  300.       break;
  301.     }
  302.  
  303.   /* If -d appeared, print version identification */
  304.   if (e_methods.trace_level > 0)
  305.     fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
  306.         JVERSION, JCOPYRIGHT);
  307.  
  308.   /* Select the input and output files */
  309.  
  310. #ifdef TWO_FILE_COMMANDLINE
  311.  
  312. #  ifdef MSDOS
  313.  
  314.   if (optind < argc-2 || optind > argc-1) {
  315.     usage(argv[0]);
  316.   }
  317.   fix_msdos_filename(infname, argv[optind], input_ext);
  318.   if (optind == argc-2) {
  319.     fix_msdos_filename(outfname, argv[optind+1], JPEG_EXT);
  320.   } else {
  321.     fix_msdos_filename(outfname, argv[optind], JPEG_EXT);
  322.   }
  323.   if ((cinfo.input_file = fopen(infname, READ_BINARY)) == NULL) {
  324.     fprintf(stderr, "%s: can't open %s\n", argv[0], infname);
  325.     exit(2);
  326.   }
  327.   if ((cinfo.output_file = fopen(outfname, WRITE_BINARY)) == NULL) {
  328.     fprintf(stderr, "%s: can't open %s\n", argv[0], outfname);
  329.     exit(2);
  330.   }
  331.  
  332. #  else
  333.  
  334.   if (optind != argc-2) {
  335.     fprintf(stderr, "%s: must name one input and one output file\n", argv[0]);
  336.     usage(argv[0]);
  337.   }
  338.   if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
  339.     fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
  340.     exit(2);
  341.   }
  342.   if ((cinfo.output_file = fopen(argv[optind+1], WRITE_BINARY)) == NULL) {
  343.     fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind+1]);
  344.     exit(2);
  345.   }
  346.  
  347. #  endif
  348.  
  349. #else /* not TWO_FILE_COMMANDLINE -- use Unix style */
  350.  
  351.   cinfo.input_file = stdin;    /* default input file */
  352.   cinfo.output_file = stdout;    /* always the output file */
  353.  
  354.   if (optind < argc-1) {
  355.     fprintf(stderr, "%s: only one input file\n", argv[0]);
  356.     usage(argv[0]);
  357.   }
  358.   if (optind < argc) {
  359.     if ((cinfo.input_file = fopen(argv[optind], READ_BINARY)) == NULL) {
  360.       fprintf(stderr, "%s: can't open %s\n", argv[0], argv[optind]);
  361.       exit(2);
  362.     }
  363.   }
  364.  
  365. #endif /* TWO_FILE_COMMANDLINE */
  366.  
  367.   /* Figure out the input file format, and set up to read it. */
  368.   select_file_type(&cinfo);
  369.  
  370.   /* Do it to it! */
  371.   jpeg_compress(&cinfo);
  372.  
  373.   /* Release memory. */
  374.   j_c_free_defaults(&cinfo);
  375. #ifdef MEM_STATS
  376.   if (e_methods.trace_level > 0) /* Optional memory-usage statistics */
  377.     j_mem_stats();
  378. #endif
  379.  
  380.   /* All done. */
  381.   exit(0);
  382. }
  383.